from django.conf import settings
from django import template
from django.template import resolve_variable
from django.core.cache import cache
from django.core.urlresolvers import reverse
from blogs.models import Blog, Tag, Link, Post, Comment

register = template.Library()

# TAG CLOUD
def generate_tag_list(blog_slug):
    '''
    Builds a list of tags for the given blog.
    
    Parameters:
    blog - The Blog object
    '''
    def count_not_zero(x): return x.ref_count > 0 
    tag_list = filter(count_not_zero, Tag.objects.filter(blog=blog_slug).order_by('name'))
    
    if len(tag_list) > 0:
        tags = []
        total_count = float(len(tag_list))
        
        bucket_count = 8 # The number of different buckets (for font sizes) to drop tags in
        max_tag = max(tag_list) # Tag with most reference count
        min_tag = min(tag_list) # Tag with least reference count
        
        # Different in value between each bucket
        delta = (max_tag.ref_count - min_tag.ref_count) / float(bucket_count)
        
        # Threshold
        thresholds = [min_tag.ref_count + i*delta for i in range(1,bucket_count)]
        buckets = [100 + i*5 for i in range(bucket_count)]
        
        import bisect
        for tag in tag_list:
            count = tag.ref_count
            index = bisect.bisect_left(thresholds, count)
            
            if count > 0:
                font_percent = buckets[index]
                tags.append({
                    'name': tag.name, 
                    'percent': font_percent, # Font size in percent to use for tag cloud
                })
        return tags
    
    return None

@register.tag()
def load_tag_cloud(parser, token):
    '''
    {% load_tag_cloud %}
    
    Takes exactly one parameter: the slug of the blog to load tags for.
    '''
    try:
        tag_name, blog_slug = token.contents.split()
    except ValueError:
        raise template.TemplateSyntaxError(
            "%s tag requires one argument" % token.contents[0])
    return TagListObject(blog_slug)


class TagListObject(template.Node):
    
    def __init__(self, blog_slug):
        self.blog_slug = blog_slug
    
    def render(self, context):
        blog_slug = resolve_variable(self.blog_slug, context)
        cache_key = 'Blog:%s_tags' % blog_slug
        tag_list = cache.get(cache_key)
        
        if tag_list == None:
            tag_list = generate_tag_list(blog_slug)
            cache.set(cache_key, tag_list, settings.DEFAULT_CACHE_TIME)

        context['blog_tags'] = tag_list

        return ''
        
        
# ARCHIVES
@register.tag()
def load_archives(parser, token):
    '''
    {% load_archives %}
    '''
    try:
        tag_name, blog_slug = token.contents.split()
    except ValueError:
        raise template.TemplateSyntaxError(
            "%s tag requires one argument" % token.contents[0])
    return ArchivesNode(blog_slug)

@register.filter
def int2month(value):
    months = ["January",
          "February",
          "March",
          "April",
          "May",
          "June",
          "July",
          "August",
          "September",
          "October",
          "November",
          "December"]
    return months[int(value)-1]
    
@register.filter
def pad(value):
    if value < 10:
        return '0%s' % value
    else:
        return value

class ArchivesNode(template.Node):

    
    def __init__(self, blog_slug=None):
        self.blog_slug = blog_slug
    
    def render(self, context):
        blog_slug = resolve_variable(self.blog_slug, context)
        
        cache_key = 'Blog:%s_archive_links' % blog_slug
        archive_links = cache.get(cache_key)
        
        if archive_links == None:
            archive_links = [] 
            months = ["January",
                "February",
                "March",
                "April",
                "May",
                "June",
                "July",
                "August",
                "September",
                "October",
                "November",
                "December"
            ]
    
	    from django.db import connection
            cursor = connection.cursor()
	    cursor.execute('SELECT DISTINCT MONTH(pub_date), YEAR(pub_date) FROM blogs_post WHERE blog_id = \'%s\' AND pub_date IS NOT NULL ORDER BY pub_date DESC' % blog_slug)
	    rows = cursor.fetchall()

            for row in rows:
	        month = row[0]
	        year = row[1]

                label = '%s %s' % (int2month(month), year)
		key = '%s %s' % (months[month-1], year)
                    
		url = reverse('blogs.main.archives_month',\
		        args=[blog_slug, year, pad(month)])

                archive_links.append({'label': label, 'url': url})

            cache.set(cache_key, archive_links, settings.DEFAULT_CACHE_TIME)
            
        context['archive_links'] = archive_links

        return ''
        
     
# BLOGROLL
@register.tag()
def load_blogroll(parser, token):
    '''
    {% load_blogroll %}
    '''
    try:
        tag_name, blog_slug = token.contents.split()
    except ValueError:
        raise template.TemplateSyntaxError(
            "%s tag requires one argument" % token.contents[0])
    return LinkNode(blog_slug)
    
    
class LinkNode(template.Node):

    def __init__(self, blog_slug=None):
        self.blog_slug = blog_slug
    
    def render(self, context):
        blog_slug = resolve_variable(self.blog_slug, context)
        
        cache_key = 'Blog:%s_blogroll' % blog_slug
        links = cache.get(cache_key)
        
        if links == None:
            links = Link.objects.filter(blog=blog_slug, active=True).order_by('name')
            cache.set(cache_key, list(links), settings.DEFAULT_CACHE_TIME)
            
        context['links'] = links

        return ''
        
        
# LATEST COMMENTS
@register.tag()
def load_latest_comments(parser, token):
    '''
    {% load_latest_comments %}
    '''
    
    return LatestCommentsNode()

@register.tag()
def load_latest_blog_comments(parser, token):
    '''
    {% load_latest_blog_comments %}
    
    Takes exactly one parameter: the slug of the blog to load tags for.
    '''
    
    try:
        tag_name, blog_slug = token.contents.split()
    except ValueError:
        raise template.TemplateSyntaxError(
            "%s tag requires one argument" % token.contents[0])
    
    return LatestCommentsNode(blog_slug)


class LatestCommentsNode(template.Node):
    
    def __init__(self, blog_slug=None):
        self.blog_slug = blog_slug
    
    def render(self, context):
        latest = None
        
        if self.blog_slug:
            blog_slug = resolve_variable(self.blog_slug, context)
            
            cache_key = 'Blog:%s_latest_comments' % blog_slug
            latest = cache.get(cache_key)
            
            if latest == None:
                latest = Comment.objects.filter(blog=blog_slug).order_by('-date')[:10]
                cache.set(cache_key, list(latest), settings.DEFAULT_CACHE_TIME)
        else:
            cache_key = 'latest_comments'
            latest = cache.get(cache_key)
            
            if latest == None:
                latest = Post.objects.filter(pub_date__isnull=False).order_by('-date')[:10]
                cache.set(cache_key, list(latest), settings.DEFAULT_CACHE_TIME)
            
        context['latest_comments'] = latest

        return ''


# LATEST POSTS
@register.tag()
def load_latest_posts(parser, token):
    '''
    {% load_latest_posts %}
    '''
    
    return LatestPostsNode()

@register.tag()
def load_latest_blog_posts(parser, token):
    '''
    {% load_latest_blog_posts %}
    
    Takes exactly one parameter: the slug of the blog to load tags for.
    '''
    
    try:
        tag_name, blog_slug = token.contents.split()
    except ValueError:
        raise template.TemplateSyntaxError(
            "%s tag requires one argument" % token.contents[0])
    
    return LatestPostsNode(blog_slug)


class LatestPostsNode(template.Node):
    
    def __init__(self, blog_slug=None):
        self.blog_slug = blog_slug
    
    def render(self, context):
        latest = None
        
        if self.blog_slug:
            blog_slug = resolve_variable(self.blog_slug, context)
            
            cache_key = 'Blog:%s_latest_posts' % blog_slug
            latest = cache.get(cache_key)
            
            if latest == None:
                latest = Post.objects.filter(blog=blog_slug, pub_date__isnull=False).order_by('-pub_date')[:10]
                cache.set(cache_key, list(latest), settings.DEFAULT_CACHE_TIME)
        else:
            cache_key = 'latest_posts'
            latest = cache.get(cache_key)
            
            if latest == None:
                latest = Post.objects.filter(pub_date__isnull=False).order_by('-pub_date')[:10]
                cache.set(cache_key, list(latest), settings.DEFAULT_CACHE_TIME)
            
        context['latest_posts'] = latest

        return ''
